home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Atari Mega Archive 1
/
Atari Mega Archive - Volume 1.iso
/
telecomm
/
sticpsrc.lzh
/
SOURCE.ARC
/
ATARI_IO.C
< prev
next >
Wrap
C/C++ Source or Header
|
1990-07-22
|
9KB
|
469 lines
/* Atari ST async I/O routines, used by "attach asy ..." */
/* written by Rob Janssen, PE1CHL */
#include <stdio.h>
#include <time.h>
#ifndef __TURBOC__
#include <osbind.h> /* os interface defines */
# ifdef MWC
# undef Rsconf
# define Rsconf(a,b,c,d,e,f) (unsigned long) xbios(15,a,b,c,d,e,f)
# endif
#endif
#ifndef Bconmap
# define Bconmap(dev) (unsigned) xbios(44,dev) /* TT Xbios Bconmap() function */
#endif
#include "global.h"
#include "mbuf.h"
#include "internet.h"
#include "iface.h"
#include "asy.h"
#include "atari.h"
struct asy asy[ASY_MAX];
unsigned nasy;
/* Interface list header */
extern struct interface *ifaces;
static int asy_setbuf();
/* Initialize asynch port "dev" */
int
asy_init(dev,arg1,arg2,bufsize)
int16 dev;
char *arg1,*arg2;
unsigned bufsize;
{
register struct asy *ap;
unsigned tbufsize;
unsigned oldmap;
unsigned long rsconf;
#ifdef DEBUG
printf("asy_init(%d,%s,%s,%d)\n",dev,arg1,arg2,bufsize); fflush(stdout);
#endif
ap = &asy[dev];
ap->addr = atoi(arg1); /* device number */
ap->vec = htoi(arg2); /* used for mode flags */
if (ap->addr == 0 || ap->addr == 2) /* backward compatability... */
ap->addr++; /* (old devs 0,2 are now 1,3) */
if (ap->addr == 4 || ap->addr == 5 || ap->addr > 15) {
printf("asy%d: Bad address %d\n",dev,ap->addr);
return -1;
}
#ifdef DEBUG
printf("asy_init: ap->addr=%u, ap->vec=%u\n",ap->addr,ap->vec); fflush(stdout);
#endif
/* devno's above 5 need Bconmap() to be configured */
if (ap->addr >= MODEM1) {
if ((oldmap = Bconmap(ap->addr)) >= 44) {
printf("Warning: cannot configure asy dev %d\n",ap->addr);
return 0;
}
}
/* determine buffering. everybody has receive buffer, but a transmit */
/* buffer is NOT used for MIDI and RS232-direct */
tbufsize = 0; /* default no tx buffer */
switch (ap->addr)
{
case RS232:
if (ap->vec & 1) /* direct buffer access? */
goto no_txbuf;
default:
if ((tbufsize = bufsize) > 1024) /* set tx buffer */
tbufsize = 1024;
case MIDI:
no_txbuf:
if (asy_setbuf(ap,bufsize,tbufsize)) {
if (ap->addr >= MODEM1)
Bconmap(oldmap);
return -1;
}
break;
}
if (ap->addr != MIDI) {
rsconf = Rsconf(-1,-1,-1,-1,-1,-1); /* read present config */
#ifdef DEBUG
printf("asy_init: rsconf was %08lx\n",rsconf); fflush(stdout);
#endif
/* setup for no flow, 8 bits, no parity, leave rest as-is */
Rsconf(-1,0,(int) ((rsconf>>24) & 0x81) | 0x08,-1,(int) (rsconf>>8) & 0x77,-1);
}
if (ap->addr >= MODEM1)
Bconmap(oldmap);
return 0;
}
static int
asy_setbuf (ap,rbufsize,tbufsize)
register struct asy *ap;
unsigned rbufsize,tbufsize;
{
register struct iorec *ip;
char *rbufp,*tbufp;
char i_state;
#ifdef DEBUG
printf("asy_setbuf: addr=%u rbufsize=%u tbufsize=%u\n",ap->addr,rbufsize,tbufsize); fflush(stdout);
#endif
if (ap->addr == MIDI)
tbufsize = 0; /* MIDI can't have tx buf */
if ((rbufp = malloc(rbufsize)) == NULLCHAR){
printf("asy %d: No space for rx buffer\n",ap->addr);
return -1;
}
if (tbufsize != 0){
if ((tbufp = malloc(tbufsize)) == NULLCHAR){
free(rbufp);
printf("asy %d: No space for tx buffer\n",ap->addr);
return -1;
}
}
ip = (struct iorec *) Iorec((ap->addr == MIDI)? 2 : 0);
ap->in = ip;
ap->out = ip + 1;
i_state = disable();
/* Save original IOREC values */
memcpy(&ap->oldin,ap->in,sizeof(struct iorec));
if (ap->addr != MIDI)
memcpy(&ap->oldout,ap->out,sizeof(struct iorec));
/* Set up receiver FIFO */
ap->in->ibuf = rbufp;
ap->in->ibufsiz = rbufsize;
ap->in->ibufhd = ap->in->ibuftl = 0;
ap->in->ibuflow = 0;
ap->in->ibufhi = rbufsize;
if (tbufsize != 0) {
/* Set up transmitter FIFO */
ap->out->ibuf = tbufp;
ap->out->ibufsiz = tbufsize;
ap->out->ibufhd = ap->out->ibuftl = 0;
ap->out->ibuflow = 0;
ap->out->ibufhi = tbufsize;
}
restore(i_state);
return 0;
}
void
asy_stop(iface)
struct interface *iface;
{
register struct asy *ap;
char i_state;
#ifdef DEBUG
printf("asy_stop(0x%lx), dev=%d\n",iface,iface->dev);
fflush(stdout);
#endif
ap = &asy[iface->dev];
if (ap->in == NULL) /* no Iorec setup done? */
return;
if (ap->addr != MIDI)
while (ap->out->ibufhd != ap->out->ibuftl)
; /* wait until all transmitted */
/* Restore old iorecs */
i_state = disable();
free(ap->in->ibuf); /* free the buffer */
memcpy(ap->in,&ap->oldin,sizeof(struct iorec));
if (ap->addr != MIDI)
{
#if 0
free(ap->out->ibuf); /* transmit buffer too */
#endif
memcpy(ap->out,&ap->oldout,sizeof(struct iorec));
}
restore(i_state);
}
/* Asynchronous line I/O control */
asy_ioctl(interface,argc,argv)
struct interface *interface;
int argc;
char *argv[];
{
if(argc < 1){
printf("%d\r\n",asy[interface->dev].speed);
return 0;
}
return asy_speed(interface->dev,atoi(argv[0]));
}
/* Set asynch line speed */
int
asy_speed(dev,speed)
int dev;
unsigned int speed;
{
register struct asy *ap;
register int sp;
unsigned oldmap;
long sav_ssp;
#ifdef DEBUG
printf("asy_speed(%d,%u)\n",dev,speed); fflush(stdout);
#endif
if(speed == 0 || dev >= nasy)
return -1;
ap = &asy[dev];
switch (ap->addr)
{
case MIDI:
/* midi can run on 500000 or 614400Hz clock (hardware mod) */
switch (speed)
{
case 0x9600: /* = 38400 unsigned... */
case 31250:
case 16: /* divide-by-16 */
sp = 0x95;
break;
case 9600:
case 7812:
case 64: /* divide-by-64 */
sp = 0x96;
break;
default:
printf("asy: bad speed on MIDI\n");
return -1;
}
sav_ssp = Super(NULL); /* access chip */
*((char *) 0xfffffc04L) = 0x03; /* RESET it */
*((char *) 0xfffffc04L) = sp; /* set new program */
Super(sav_ssp);
break;
default:
switch (speed)
{
case 19200: sp = 0; break;
case 9600: sp = 1; break;
case 4800: sp = 2; break;
case 2400: sp = 4; break;
case 1200: sp = 7; break;
case 600: sp = 8; break;
case 300: sp = 9; break;
default:
if (speed > 32) {
printf("asy: bad speed on RS232\n");
return -1;
}
sp = speed;
break;
}
/* devno's above 5 need Bconmap() to be configured */
if (ap->addr >= MODEM1) {
if ((oldmap = Bconmap(ap->addr)) >= 44) {
printf("Warning: cannot set speed for asy dev %d\n",ap->addr);
return 0;
}
}
Rsconf(sp,-1,-1,-1,-1,-1); /* set new speed */
if (ap->addr >= MODEM1)
Bconmap(oldmap);
break;
}
ap->speed = speed;
return 0;
}
/* Send a buffer to serial transmitter */
asy_output(dev,buf,cnt)
unsigned dev;
char *buf;
unsigned short cnt;
{
register struct asy *ap;
register struct iorec *ip;
long sav_ssp;
#ifdef XDEBUG
int i;
printf("asy_output(%d,0x%lx,%d) data=",dev,buf,cnt);
for (i = 0; i < cnt; i++)
printf("%02x ",buf[i] & 0xff);
printf("\n");
fflush(stdout);
#endif
if (dev >= nasy || cnt == 0) /* these "cannot happen" */
return;
ap = &asy[dev];
switch (ap->addr)
{
case MIDI:
Midiws(cnt - 1,buf); /* write MIDI (unbuffered...) */
break;
case RS232:
if (ap->vec & 1) {
ip = ap->out;
if(ip->ibufhd != ip->ibuftl)
return; /* Already busy */
/* fake the output record to transmit data */
ip->ibuf = buf;
ip->ibufsiz = cnt;
ip->ibufhd = 0;
ip->ibuftl = cnt - 1;
ip->ibuflow = 0;
ip->ibufhi = cnt + 1;
sav_ssp = Super(NULL); /* supervisor mode to access chip */
/* kick the chip to start interrupts */
*((char *) (0xfffffa01L+46)) = ip->ibuf[0];
Super(sav_ssp); /* back to user mode */
break;
}
default:
do {
Bconout(ap->addr,*buf++);
}
while (--cnt);
break;
}
}
/* Receive characters from asynch line
* Returns count of characters read
*/
int16
asy_recv(dev,buf,cnt)
int dev;
register char *buf;
unsigned cnt;
{
unsigned tot;
register struct asy *ap;
register struct iorec *ip;
#ifdef XDEBUG
int i;
char *b = buf;
#endif
ap = &asy[dev];